package com.kly.user.task.v2.appflyers;

import cn.hutool.core.net.NetUtil;
import cn.hutool.crypto.SecureUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.api.config.annotation.NacosValue;
import com.fqgj.common.utils.CollectionUtils;
import com.fqgj.log.factory.LogFactory;
import com.fqgj.log.interfaces.Log;
import com.google.common.collect.Maps;
import com.kly.user.db.dao.UserDao;
import com.kly.user.db.dao.UserTaskDetailDao;
import com.kly.user.db.dao.UserWlmDao;
import com.kly.user.db.dbo.PaidOrderDBO;
import com.kly.user.db.dbo.UserAfDBO;
import com.kly.user.db.entity.UserEntity;
import com.kly.user.db.entity.UserTaskDetailEntity;
import com.kly.user.enums.AppCodeEnum;
import com.kly.user.enums.AppsFlyerEventDefType;
import com.kly.user.enums.UserStatus;
import com.kly.user.firebase.FirebaseEventTrackingService;
import com.kly.user.service.AppsflyerService;
import com.kly.user.task.enums.TaskTypeEnum;
import com.kly.user.utils.LittleOrangeService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * appflyer事件推送
 *
 * @author linqu
 */
@Service
public class PushToAppflyersV2Task {

    private static Log logger = LogFactory.getLog(PushToAppflyersV2Task.class);
    private String localIP = NetUtil.getLocalhostStr();

    @NacosValue(value = "${task.job.executor.ip}", autoRefreshed = true)
    private String taskJobExecutor;
    @NacosValue(value = "${push.to.af.switch:true}", autoRefreshed = true)
    private Boolean pushToAfSwitch;
    @NacosValue(value = "${appsflyer.auth}", autoRefreshed = true)
    private String auth;
    @NacosValue(value = "${pp.appsflyer.auth:11111}", autoRefreshed = true)
    private String ppAuth;
    @Resource
    private UserTaskDetailDao userTaskDetailDao;
    @Resource
    AppsflyerService appsflyerService;
    @Resource
    UserDao userDao;
    @Resource
    UserWlmDao userWlmDao;
    @NacosValue(value = "${amount.threshold.value:0.2}", autoRefreshed = true)
    private String amountThresholdValue;
    @Resource
    private FirebaseEventTrackingService firebaseEventTrackingService;

    /**
     * 执行频率：10分钟
     */
    @Scheduled(fixedDelay = 1000 * 600)
    public void addDataToPool() {
        logger.info("====addDataToPool start");
        if (!taskJobExecutor.contains(localIP)) {
            logger.info("=============addDataToPool, currentLocalAddress:{}, onlyExecuteTaskIn:{}", localIP, taskJobExecutor);
            return;
        }
        if (!pushToAfSwitch) {
            logger.info("=============addDataToPool, pushToAfSwitch:{}", pushToAfSwitch);
            return;
        }


        // 获取已存在的事件数据集合
        final Map<String, List<String>> existsTaskLatestDayMap = getExistsTaskLatestDay(TaskTypeEnum.PUSH_DATA_TO_APPSFLYER_V2);

        // 添加注册事件
        addRegister(existsTaskLatestDayMap);

        // 添加建联事件
        addConnect(existsTaskLatestDayMap);

        // 添加支付事件
        addPaidOrderToTaskDetail(existsTaskLatestDayMap);

    }

    /**
     * 执行频率：10分钟
     */
//    @Scheduled(fixedDelay = 1000 * 600)
    public void addPoolForFirebase() {
        logger.info("====addDataToPool start");
        if (!taskJobExecutor.contains(localIP)) {
            logger.info("=============addDataToPool, currentLocalAddress:{}, onlyExecuteTaskIn:{}", localIP, taskJobExecutor);
            return;
        }
        if (!pushToAfSwitch) {
            logger.info("=============addDataToPool, pushToAfSwitch:{}", pushToAfSwitch);
            return;
        }


        // 获取已存在的事件数据集合
        final Map<String, List<String>> existsTaskLatestDayMap = getExistsTaskLatestDay(TaskTypeEnum.PUSH_DATA_TO_FIREBASE_V1);

        // 添加注册事件
        addRegister(existsTaskLatestDayMap);

        // 添加建联事件
        addConnect(existsTaskLatestDayMap);

        // 添加支付事件
        addPaidOrderToTaskDetail(existsTaskLatestDayMap);

    }


    /**
     * 推送数据到appflyers执行频率：5分钟
     */
    @Scheduled(fixedDelay = 1000 * 300)
    public void run() {
        logger.info("====PushToAppflyersV2Task start");
        if (!taskJobExecutor.contains(localIP)) {
            logger.info("=============PushToAppflyersV2Task, currentLocalAddress:{}, onlyExecuteTaskIn:{}", localIP, taskJobExecutor);
            return;
        }
        if (!pushToAfSwitch) {
            logger.info("=============PushToAppflyersV2Task, pushToAfSwitch:{}", pushToAfSwitch);
            return;
        }
        pushToAppflyers();
    }

    /**
     * 推送数据到appflyers执行频率：10分钟
     */
    @Scheduled(fixedDelay = 1000 * 600)
    public void run2() {
        logger.info("====PushToAppflyersV2Task start");
        if (!taskJobExecutor.contains(localIP)) {
            logger.info("=============PushToAppflyersV2Task, currentLocalAddress:{}, onlyExecuteTaskIn:{}", localIP, taskJobExecutor);
            return;
        }
        if (!pushToAfSwitch) {
            logger.info("=============PushToAppflyersV2Task, pushToAfSwitch:{}", pushToAfSwitch);
            return;
        }

        // 推送firebase埋点事件
        pushToFirebase();
    }

    private void addConnect(Map<String, List<String>> existsTaskLatestDayMap) {
        // 只推送：2024-03-11 00:00:00 之后注册的用户数据
        final List<UserAfDBO> userEntities = userWlmDao.listConnectUsersLatestDayFromAppflyers();
        if (CollectionUtils.isEmpty(userEntities)) {
            return;
        }
        for (UserAfDBO user : userEntities) {
            final List<String> existsUsers = existsTaskLatestDayMap.get(AppsFlyerEventDefType.Connect.getEventCode());
            String uid = SecureUtil.md5(user.getUserCode() + user.getUserCodeWlm());
            if (CollectionUtils.isEmpty(existsUsers) || !existsUsers.contains(uid)) {
                final HashMap<String, Object> params = Maps.newHashMap();
                params.put("userCode", user.getUserCode());
                params.put("uid", uid);
                params.put("appCode", user.getAppCode());
                appsflyerService.asyncTraceEvent(AppsFlyerEventDefType.Connect, params);
            }
        }
    }

    private void addRegister(Map<String, List<String>> existsTaskLatestDayMap) {
        final List<UserEntity> userEntities = userDao.listUsersLatestDayFromAppflyers();
        if (CollectionUtils.isEmpty(userEntities)) {
            return;
        }
        for (UserEntity user : userEntities) {
            if (UserStatus.ACTIVE.getType() != user.getStatus()) {
                logger.info("====无效用户===userCode:{}", user.getUserCode());
                continue;
            }
            final List<String> existsUsers = existsTaskLatestDayMap.get(AppsFlyerEventDefType.Registration.getEventCode());
            if (CollectionUtils.isEmpty(existsUsers) || !existsUsers.contains(user.getUserCode())) {
                final HashMap<String, Object> params = Maps.newHashMap();
                params.put("userCode", user.getUserCode());
                params.put("appCode", user.getAppCode());
                if (AppCodeEnum.MEBOO.getAppCode().equals(user.getAppCode())) {
                    logger.info("============添加注册事件，meboo用户已在客户端埋点，跳过用户【{}】", user.getUserCode());
                    continue;
                }
                appsflyerService.asyncTraceEvent(AppsFlyerEventDefType.Registration, params);
            }
        }
    }



    private void addPaidOrderToTaskDetail(Map<String, List<String>> existsTaskLatestDayMap) {

        final List<PaidOrderDBO> paidOrderDBOS = userTaskDetailDao.listAllPaidOrdersLatestDayFromAppflyers();
        if (CollectionUtils.isEmpty(paidOrderDBOS)) {
            return;
        }

        for (PaidOrderDBO dbo : paidOrderDBOS) {

            // d0购买
            if (dbo.getTodayPaidFlag() == 1) {
                final List<String> orders = existsTaskLatestDayMap.get(AppsFlyerEventDefType.D0_Purchase.getEventCode());
                if (CollectionUtils.isEmpty(orders) || !orders.contains(dbo.getOrderNo())) {
                    addTaskDetail(dbo, AppsFlyerEventDefType.D0_Purchase);
                }
            }

            // 添加购买
            if (!AppCodeEnum.MEBOO.getAppCode().equals(dbo.getAppCode())) {
                final List<String> purchaseOrders = existsTaskLatestDayMap.get(AppsFlyerEventDefType.Purchase.getEventCode());
                if (CollectionUtils.isEmpty(purchaseOrders) || !purchaseOrders.contains(dbo.getOrderNo())) {
                    addTaskDetail(dbo, AppsFlyerEventDefType.Purchase);
                }
            }


        }
    }

    private void addTaskDetail(PaidOrderDBO dbo, AppsFlyerEventDefType event) {
        final HashMap<String, Object> params = Maps.newHashMap();
        params.put("amount", dbo.getPaidAmount().multiply(new BigDecimal(amountThresholdValue)));
        params.put("productCode", dbo.getProductCode());
        params.put("userCode", dbo.getUserCode());
        params.put("orderNo", dbo.getOrderNo());
        params.put("appCode", dbo.getAppCode());
        appsflyerService.asyncTraceEvent(event, params);
    }

    private Map<String, List<String>> getExistsTaskLatestDay(TaskTypeEnum taskTypeEnum) {
        final List<UserTaskDetailEntity> userTaskDetailEntities = userTaskDetailDao.listAllTaskLatestDay(taskTypeEnum.getCode());
        if (CollectionUtils.isEmpty(userTaskDetailEntities)) {
            return Maps.newHashMap();
        }

        List<String> d0PurchaseList = userTaskDetailEntities.parallelStream().filter(o -> AppsFlyerEventDefType.D0_Purchase.getEventCode().equals(o.getExtend())).map(o -> {
            String request = o.getRequest();
            if (StringUtils.isNotBlank(request)) {
                return JSONObject.parseObject(request).getString("orderNo");
            }
            return "";
        }).collect(Collectors.toList());

        List<String> purchaseList = userTaskDetailEntities.parallelStream().filter(o -> AppsFlyerEventDefType.Purchase.getEventCode().equals(o.getExtend())).map(o -> {
            String request = o.getRequest();
            if (StringUtils.isNotBlank(request)) {
                return JSONObject.parseObject(request).getString("orderNo");
            }
            return "";
        }).collect(Collectors.toList());

        List<String> connectList = userTaskDetailEntities.parallelStream().filter(o -> AppsFlyerEventDefType.Connect.getEventCode().equals(o.getExtend())).map(o -> {
            String request = o.getRequest();
            if (StringUtils.isNotBlank(request)) {
                return JSONObject.parseObject(request).getString("uid");
            }
            return "";
        }).collect(Collectors.toList());

        List<String> registerList = userTaskDetailEntities.parallelStream().filter(o -> AppsFlyerEventDefType.Registration.getEventCode().equals(o.getExtend())).map(o -> {
            String request = o.getRequest();
            if (StringUtils.isNotBlank(request)) {
                return JSONObject.parseObject(request).getString("customer_user_id");
            }
            return "";
        }).collect(Collectors.toList());

        Map<String, List<String>> pushEventMap = Maps.newHashMap();

        if (CollectionUtils.isNotEmpty(d0PurchaseList)) {
            pushEventMap.put(AppsFlyerEventDefType.D0_Purchase.getEventCode(), d0PurchaseList);
        }
        if (CollectionUtils.isNotEmpty(purchaseList)) {
            pushEventMap.put(AppsFlyerEventDefType.Purchase.getEventCode(), purchaseList);
        }
        if (CollectionUtils.isNotEmpty(registerList)) {
            pushEventMap.put(AppsFlyerEventDefType.Registration.getEventCode(), registerList);
        }
        if (CollectionUtils.isNotEmpty(connectList)) {
            pushEventMap.put(AppsFlyerEventDefType.Connect.getEventCode(), connectList);
        }

        return pushEventMap;
    }

    private void pushToFirebase() {
        final List<UserTaskDetailEntity> waitingProcessTasks = userTaskDetailDao.queryNeedProcessJobsByType(TaskTypeEnum.PUSH_DATA_TO_FIREBASE_V1.getCode(), 5);
        if (CollectionUtils.isEmpty(waitingProcessTasks)) {
            return;
        }
        for (UserTaskDetailEntity task : waitingProcessTasks) {
            logger.info("================Firebase埋点事件操作开始, task:{}", JSONObject.toJSONString(task));
            Integer status = task.getStatus();
            try {
                boolean success = firebaseEventTrackingService.collect(task.getRequest());
                if (success) {
                    status = 1;
                }
                String result = success ? "success" : "fail";
                userTaskDetailDao.updateTask(task.getId(), status, result);
                logger.info("================Firebase埋点事件操作结束, task:{}, result:{}", JSONObject.toJSONString(task), result);
            } catch (Exception e) {
                userTaskDetailDao.updateTask(task.getId(), status, e.getMessage());
                logger.error("================Firebase埋点事件操作失败, task:{}", JSONObject.toJSONString(task), e);
            }
        }
    }

    private void pushToAppflyers() {
        final List<UserTaskDetailEntity> waitingProcessTasks = userTaskDetailDao.queryNeedProcessJobsByType(TaskTypeEnum.PUSH_DATA_TO_APPSFLYER_V2.getCode(), 5);
        if (CollectionUtils.isEmpty(waitingProcessTasks)) {
            return;
        }
        for (UserTaskDetailEntity task : waitingProcessTasks) {
            logger.info("PushToAppFlyerRetryTaskStart===, task:{}", JSONObject.toJSONString(task));
            Integer status = task.getStatus();
            try {
                final String result = retryPushToAf(task);
                if (com.fqgj.common.utils.StringUtils.isNotEmpty(result) && result.equals("ok")) {
                    status = 1;
                }

                userTaskDetailDao.updateTask(task.getId(), status, result);
                logger.info("PushToAppFlyerRetryTaskEnd===, task:{}, result:{}", JSONObject.toJSONString(task), result);

            } catch (Exception e) {
                userTaskDetailDao.updateTask(task.getId(), status, e.getMessage());
                logger.error("PushToAppFlyerRetryTaskError, task:{}", JSONObject.toJSONString(task), e);
            }
        }
    }

    public String retryPushToAf(UserTaskDetailEntity task) {
        final String appCode = StringUtils.isBlank(task.getTaskDesc()) ? AppCodeEnum.MEBOO.getAppCode() : task.getTaskDesc();
        String apiSecret = auth;
        if (appCode.equals(AppCodeEnum.PP.getAppCode())) {
            apiSecret = ppAuth;
        }
        final String result = LittleOrangeService.post(task.getCallbackUrl(), apiSecret, task.getRequest());
        logger.info("PushDataToAppsFlyerSuccess, body:{}, result:{}", task.getRequest(), result);
        return result;
    }

//    public static void main(String[] args) {
//        final String result = LittleOrangeService.post("https://api2.appsflyer.com/inappevent/com.kly.meboo?monetary=N/A&content_id=N/A", "RVdnrbmFm9R2fusE3uUidc", "{\"eventValue\":{\"fb_mobile_complete_registration\":1},\"eventTime\":\"2024-03-08 14:23:59.123\",\"eventName\":\"Registration\",\"appsflyer_id\":\"1697514491449-4662186095297607826\",\"customer_user_id\":\"1765986800659169280\"}");
//        System.out.println(result);
//    }
}